package org.dromara.common.core.enums

import cn.hutool.core.util.StrUtil
import org.dromara.common.core.exception.ServiceException
import org.dromara.common.core.utils.StringUtils
import java.util.*
import java.util.function.Function
import java.util.stream.Collectors

/**
 * 业务状态枚举
 *
 * @author may
 * @updater LikeYouDo
 * @date 2025/1/10 10:46
 */
enum class BusinessStatusEnum(
    /**
     * 状态
     */
    val status: String,

    /**
     * 描述
     */
    val desc: String,
) {
    /**
     * 已撤销
     */
    CANCEL("cancel", "已撤销"),
    /**
     * 草稿
     */
    DRAFT("draft", "草稿"),
    /**
     * 待审核
     */
    WAITING("waiting", "待审核"),
    /**
     * 已完成
     */
    FINISH("finish", "已完成"),
    /**
     * 已作废
     */
    INVALID("invalid", "已作废"),
    /**
     * 已退回
     */
    BACK("back", "已退回"),
    /**
     * 已终止
     */
    TERMINATION("termination", "已终止");

    companion object {

        private val STATUS_MAP: MutableMap<String, BusinessStatusEnum> =
            Arrays.stream(BusinessStatusEnum.entries.toTypedArray())
                .collect(Collectors.toConcurrentMap(BusinessStatusEnum::status, Function.identity()))

        /**
         * 根据状态获取对应的 BusinessStatusEnum 枚举
         *
         * @param status 业务状态码
         * @return 对应的 BusinessStatusEnum 枚举，如果找不到则返回 null
         */
        fun getByStatus(status: String): BusinessStatusEnum? {
            // 使用 STATUS_MAP 获取对应的枚举，若找不到则返回 null
            return STATUS_MAP[status]
        }

        /**
         * 根据状态获取对应的业务状态描述信息
         *
         * @param status 业务状态码
         * @return 返回业务状态描述，若状态码为空或未找到对应的枚举，返回空字符串
         */
        @JvmStatic
        fun findByStatus(status: String): String {
            if (StringUtils.isBlank(status)) {
                return StrUtil.EMPTY
            }
            val statusEnum = STATUS_MAP[status]
            return statusEnum?.desc ?: StrUtil.EMPTY
        }

        /**
         * 判断是否为指定的状态之一：草稿、已撤销或已退回
         *
         * @param status 要检查的状态
         * @return 如果状态为草稿、已撤销或已退回之一，则返回 true；否则返回 false
         */
        @JvmStatic
        fun isDraftOrCancelOrBack(status: String): Boolean {
            return DRAFT.status == status || CANCEL.status == status || BACK.status == status
        }

        /**
         * 判断是否为撤销，退回，作废，终止
         *
         * @param status status
         * @return 结果
         */
        @JvmStatic
        fun initialState(status: String): Boolean {
            return CANCEL.status == status || BACK.status == status || INVALID.status == status || TERMINATION.status == status
        }

        /**
         * 获取运行中的实例状态列表
         *
         * @return 包含运行中实例状态的不可变列表
         * （包含 DRAFT、WAITING、BACK 和 CANCEL 状态）
         */
        @JvmStatic
        fun runningStatus(): List<String> {
            return listOf(
                DRAFT.status,
                WAITING.status,
                BACK.status,
                CANCEL.status
            )
        }

        /**
         * 获取结束实例的状态列表
         *
         * @return 包含结束实例状态的不可变列表
         * （包含 FINISH、INVALID 和 TERMINATION 状态）
         */
        @JvmStatic
        fun finishStatus(): List<String> {
            return listOf(
                FINISH.status,
                INVALID.status,
                TERMINATION.status
            )
        }

        /**
         * 启动流程校验
         *
         * @param status 状态
         */
        @JvmStatic
        fun checkStartStatus(status: String) {
            when (status) {
                WAITING.status -> throw ServiceException("该单据已提交过申请,正在审批中！")
                FINISH.status -> throw ServiceException("该单据已完成申请！")
                INVALID.status -> throw ServiceException("该单据已作废！")
                TERMINATION.status -> throw ServiceException("该单据已终止！")
            }
            if (StringUtils.isBlank(status)) {
                throw ServiceException("流程状态为空！")
            }
        }

        /**
         * 撤销流程校验
         *
         * @param status 状态
         */
        @JvmStatic
        fun checkCancelStatus(status: String) {
            when (status) {
                CANCEL.status -> throw ServiceException("该单据已撤销！")
                FINISH.status -> throw ServiceException("该单据已完成申请！")
                INVALID.status -> throw ServiceException("该单据已作废！")
                TERMINATION.status -> throw ServiceException("该单据已终止！")
                BACK.status -> throw ServiceException("该单据已退回！")
            }
            if (StringUtils.isBlank(status)) {
                throw ServiceException("流程状态为空！")
            }
        }

        /**
         * 驳回流程校验
         *
         * @param status 状态
         */
        @JvmStatic
        fun checkBackStatus(status: String) {
            when (status) {
                BACK.status -> throw ServiceException("该单据已退回！")
                FINISH.status -> throw ServiceException("该单据已完成申请！")
                INVALID.status -> throw ServiceException("该单据已作废！")
                TERMINATION.status -> throw ServiceException("该单据已终止！")
                CANCEL.status -> throw ServiceException("该单据已撤销！")
            }
            if (StringUtils.isBlank(status)) {
                throw ServiceException("流程状态为空！")
            }
        }

        /**
         * 作废,终止流程校验
         *
         * @param status 状态
         */
        @JvmStatic
        fun checkInvalidStatus(status: String) {
            when (status) {
                FINISH.status -> throw ServiceException("该单据已完成申请！")
                INVALID.status -> throw ServiceException("该单据已作废！")
                TERMINATION.status -> throw ServiceException("该单据已终止！")
            }
            if (StringUtils.isBlank(status)) {
                throw ServiceException("流程状态为空！")
            }
        }

    }
}
